home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1992-1993 Michael Davidson.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software
- * and its documentation for any purpose and without fee is hereby
- * granted, provided that the above copyright notice appear in all
- * copies and that both that copyright notice and this permission
- * notice appear in supporting documentation.
- *
- * This software is provided "as is" without express or implied warranty.
- */
-
- /*
- * This software is derived from the Independent JPEG Group's software
- *
- * Copyright (C) 1991, 1992 Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
- *
- * For conditions of distribution and use, see the accompanying README file.
- */
-
- #include "jpeg.h"
- #include <stdlib.h>
- #include <macros.h>
-
-
- STATIC JSAMPLE **
- alloc_sarray(
- long samplesperrow,
- long numrows
- )
- {
- JSAMPLE **result;
- JSAMPLE *workspace;
- int nbytes;
- int i;
-
- nbytes = numrows * (sizeof(JSAMPLE *) + samplesperrow*sizeof(JSAMPLE));
- result = (JSAMPLE **) malloc(nbytes);
- if (result != NULL)
- {
- workspace = (JSAMPLE *) &result[numrows];
-
- for (i = 0; i < numrows; i++)
- {
- result[i] = workspace;
- workspace += samplesperrow;
- }
- }
- return result;
- }
-
- unsigned char range_tab[256 * 3];
- unsigned char *range_limit_0_255 = &range_tab[256];
-
- static void
- init_range_limit()
- {
- int i;
- unsigned char *p;
-
- p = range_tab;
-
- for (i = 0; i < 256; i++)
- *p++ = 0;
-
- range_limit_0_255 = p;
-
- for (i = 0; i < 256; i++)
- *p++ = i;
-
- for (i = 0; i < 256; i++)
- *p++ = 255;
- }
-
- void h2v1_upsample();
- /*
- * Un-subsample pixel values of a single component.
- * This version only handles integral sampling ratios.
- */
- void
- jpegUnSubSample(
- long input_cols,
- int input_rows,
- long output_cols,
- int output_rows,
- JSAMPLE **input_data,
- JSAMPLE **output_data
- )
- {
- register unsigned char *inptr;
- register unsigned char *outptr;
- register int i;
- int inrow, outrow;
- int h_expand, v_expand;
-
- h_expand = output_cols / input_cols;
- v_expand = output_rows / input_rows;
-
- outrow = 0;
- for (inrow = 0; inrow < input_rows; inrow++)
- {
- inptr = input_data[inrow];
- outptr = output_data[outrow];
-
- switch (h_expand)
- {
- #if defined(ASM)
- case 1:
- upsample_x1(outptr, inptr, input_cols);
- break;
- case 2:
- upsample_x2(outptr, inptr, input_cols);
- break;
- #else
- case 1:
- memcpy(outptr, inptr, input_cols);
- break;
- case 2:
- for (i = 0; i < input_cols; i++, inptr++, outptr += 2)
- outptr[0] = outptr[1] = inptr[0];
- break;
- #endif
- case 3:
- for (i = 0; i < input_cols; i++, inptr++, outptr += 3)
- outptr[0] = outptr[1] = outptr[2] = inptr[0];
- break;
- case 4:
- for (i = 0; i < input_cols; i++, inptr++, outptr += 4)
- outptr[0] = outptr[1] = outptr[2] = outptr[3] = inptr[0];
- break;
- }
-
- for (i = 1; i < v_expand; i++)
- memcpy(output_data[outrow+i], output_data[outrow], output_cols);
- outrow += i;
- }
- }
-
- int
- jpegScanDecode(
- FILE *fp,
- decompress_info_ptr cinfo,
- JPEG_TABLES *tables,
- int restart_interval,
- int (*put_pixels)()
- )
- {
- JBLOCK MCU_coeff_data[MAX_BLOCKS_IN_MCU];
- JBLOCK *coeff_data;
- DBLOCK_INFO MCU_info[MAX_BLOCKS_IN_MCU];
- DBLOCK_INFO *mcu_info;
- JCOEF dc_prediction[MAX_COMPS_IN_SCAN];
-
- jpeg_component_info *compptr;
- int i, n;
- int mcu_rows_in_scan;
- int mcu_row;
- int mcus_per_row;
- int mcu;
-
- int max_h_samp_factor;
- int max_v_samp_factor;
- int mcu_width; /* width (in samples) of an MCU */
- int mcu_height; /* height (in samples) of an MCU */
- int r;
-
- int warn = 0;
-
- int restarts_to_go;
- int next_restart_marker;
-
- JSAMPLE **subsampled_image[MAX_COMPS_IN_SCAN];
- JSAMPLE **fullsize_image[MAX_COMPS_IN_SCAN];
-
- int rows_in_mem; /* # of sample rows in full-size buffers */
- long fullsize_width; /* # of samples per row in full-size buffers */
- int mcu_blks;
- long pixel_rows_output; /* # of pixel rows actually emitted */
-
- r = 0;
-
- init_range_limit();
-
- if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
- return jpegError("Too many components for interleaved scan");
-
- /*
- * calculate maximum horizontal and vertical sampling factors
- */
- max_h_samp_factor = 1;
- max_v_samp_factor = 1;
-
- for (i = 0; i < cinfo->num_components; i++)
- {
- int h_samp_factor;
- int v_samp_factor;
-
- h_samp_factor = cinfo->comp_info[i].h_samp_factor;
- v_samp_factor = cinfo->comp_info[i].v_samp_factor;
-
- if (h_samp_factor <= 0 || h_samp_factor > MAX_SAMP_FACTOR)
- return jpegError("bad horizontal sampling factor");
- if (v_samp_factor <= 0 || v_samp_factor > MAX_SAMP_FACTOR)
- return jpegError("bad vertical sampling factor");
-
- if (h_samp_factor > max_h_samp_factor)
- max_h_samp_factor = h_samp_factor;
- if (v_samp_factor > max_v_samp_factor)
- max_v_samp_factor = v_samp_factor;
- }
-
- mcu_width = max_h_samp_factor * DCTSIZE;
- mcu_height = max_v_samp_factor * DCTSIZE;
-
- mcus_per_row = (cinfo->image_width + mcu_width - 1) / mcu_width;
- mcu_rows_in_scan = (cinfo->image_height + mcu_height - 1) / mcu_height;
-
- /*
- * Compute dimensions of full-size pixel buffers
- */
- rows_in_mem = mcu_height;
- fullsize_width = mcus_per_row * mcu_width;
-
- mcu_blks = 0;
- mcu_info = &MCU_info[0];
- for (i = 0; i < cinfo->comps_in_scan; i++)
- {
- int j, k;
- int subsampled_width;
-
- compptr = cinfo->cur_comp_info[i];
- subsampled_width = mcus_per_row * compptr->h_samp_factor*DCTSIZE;
-
- for (j = 0; j < compptr->v_samp_factor; j++)
- for (k = 0; k < compptr->h_samp_factor; k++)
- {
- if (mcu_blks >= MAX_BLOCKS_IN_MCU)
- return jpegError("Sampling factors too large for interleaved scan");
- mcu_info->coeff_data = &MCU_coeff_data[mcu_blks];
- mcu_info->dc_table = &tables->dc_huff_table[compptr->dc_tbl_no];
- mcu_info->ac_table = &tables->ac_huff_table[compptr->ac_tbl_no];
- mcu_info->dc_prediction = &dc_prediction[compptr->component_index];
- mcu_info->quant_table = &tables->quant_table[compptr->quant_tbl_no];
- ++mcu_info;
- ++mcu_blks;
- }
-
- /*
- * Allocate working memory:
- * subsampled_image is sample data before unsubsampling
- * fullsize_image is sample data after unsubsampling
- */
- fullsize_image[i] = alloc_sarray(fullsize_width, rows_in_mem);
- subsampled_image[i] = alloc_sarray(subsampled_width,
- compptr->v_samp_factor * DCTSIZE);
- }
-
- /*
- * Initialize to read scan data
- */
- huff_decoder_init(fp);
-
- for (i = 0; i < MAX_COMPS_IN_SCAN; i++)
- dc_prediction[i] = 0;
-
- restarts_to_go = restart_interval;
- next_restart_marker = 0;
-
- /*
- * Loop over scan's data: rows_in_mem pixel rows are processed per loop
- */
- pixel_rows_output = 0;
-
- for (mcu_row = 0; mcu_row < mcu_rows_in_scan; mcu_row++)
- {
- for (mcu = 0; mcu < mcus_per_row; mcu++)
- {
- if (restart_interval)
- {
- if (restarts_to_go == 0)
- {
- jpegCheckRestart(fp, next_restart_marker);
- restarts_to_go = restart_interval;
- next_restart_marker = (next_restart_marker + 1) & 7;
-
- for (i = 0; i < MAX_COMPS_IN_SCAN; i++)
- dc_prediction[i] = 0;
- }
- restarts_to_go--;
- }
-
- memset((void *) MCU_coeff_data, 0, mcu_blks * sizeof(JBLOCK));
-
- warn = jpegDecodeMCU(fp, mcu_blks, MCU_info);
-
- coeff_data = MCU_coeff_data;
- for (i = 0; i < cinfo->comps_in_scan; i++)
- {
- int j, k;
- compptr = cinfo->cur_comp_info[i];
-
- for (j = 0; j < compptr->v_samp_factor; j++)
- {
- JSAMPLE **srowptr = subsampled_image[i] + (j * DCTSIZE);
- for (k = 0; k < compptr->h_samp_factor; k++)
- {
- register JSAMPLE *elemptr;
- register DCTELEM *blkptr = (DCTELEM *)coeff_data++;
- register JSAMPLE *range_limit =
- range_limit_0_255 + CENTERJSAMPLE;
- register int elemr;
-
- jpegReverseDCT(blkptr); /* perform inverse DCT */
-
- for (elemr = 0; elemr < DCTSIZE; elemr++)
- {
- elemptr = srowptr[elemr] +
- (mcu * compptr->h_samp_factor + k) * DCTSIZE;
- elemptr[0] = range_limit[blkptr[0]];
- elemptr[1] = range_limit[blkptr[1]];
- elemptr[2] = range_limit[blkptr[2]];
- elemptr[3] = range_limit[blkptr[3]];
- elemptr[4] = range_limit[blkptr[4]];
- elemptr[5] = range_limit[blkptr[5]];
- elemptr[6] = range_limit[blkptr[6]];
- elemptr[7] = range_limit[blkptr[7]];
- blkptr += 8;
- }
- }
- }
- }
- }
-
-
- for (i = 0; i < cinfo->comps_in_scan; i++)
- {
- int j;
- int v_samp_factor;
- int subsampled_width;
-
- compptr = cinfo->cur_comp_info[i];
- v_samp_factor = compptr->v_samp_factor;
- subsampled_width = mcus_per_row * compptr->h_samp_factor*DCTSIZE;
-
-
- for (j = 0; j < DCTSIZE; j++)
- jpegUnSubSample(subsampled_width, v_samp_factor,
- fullsize_width, max_v_samp_factor,
- subsampled_image[i] + j * v_samp_factor,
- fullsize_image[i] + j * max_v_samp_factor);
- }
-
- n = cinfo->image_height - pixel_rows_output;
- if (n > rows_in_mem)
- n = rows_in_mem;
- if ((r = put_pixels(0, pixel_rows_output, cinfo->image_width,
- n, fullsize_image)) != 0)
- goto out;
-
- if (warn)
- {
- r = imageWarning("corrupt data in JPEG file");
- goto out;
- }
-
- pixel_rows_output += n;
-
- } /* end of outer loop */
-
- huff_decoder_term(fp);
-
- out:
- /*
- * Release working memory
- */
- for (i = 0; i < cinfo->comps_in_scan; i++)
- {
- free((void *)fullsize_image[i]);
- free((void *)subsampled_image[i]);
- }
-
- return r;
- }
-